package pairwise_model;
import preprocess.ArticleUnit;
import preprocess.Name;
import java.util.*;
import java.io.*;
public class pairwise_name {
	public Map<String, ArrayList<String>> authority = new HashMap<String, ArrayList<String>>();
	public pairwise_name(String authority_file){
		Read_Authority_Profile(authority_file);
	}
	
	public int Get_AuthorScore(ArticleUnit article1, ArticleUnit article2){
		int score = 0;
		score = Score_from_Authority(article1.getPmid(), article2.getPmid());
		if(score<0)
			score = Score_from_AuthorList(article1.getAuthor_names(), article2.getAuthor_names());
		return score;
	}
	public void Read_Authority_Profile(String filename){
		File f= new File(filename);
		FileInputStream fis;
		try {
			fis = new FileInputStream(f);
			InputStreamReader isr=new InputStreamReader(fis);
			BufferedReader br=new BufferedReader(isr);
			String line = br.readLine();
			while(line != null){
				line = line.trim();
				if(line.length()>0)
					build_author_profile(line);
				line = br.readLine();
			}
			br.close();
		}catch(IOException e){
			e.printStackTrace();
		}
	}
	
	public void build_author_profile(String line){
		if(line == null)
			return;
		String s[] = line.split("\t");
		ArrayList<String> author_list = new ArrayList<String>();
		if(!authority.containsKey(s[0])){
			for(int i=1; i<s.length; i++)
				author_list.add(s[i]);
			authority.put(s[0], author_list);
		}
	}
	
	public int Score_from_Authority(String pmid1, String pmid2){
		int score = 0;
		if(!authority.containsKey(pmid1) || !authority.containsKey(pmid2))
			return -1;
		ArrayList<String> author_list1 = authority.get(pmid1);
		ArrayList<String> author_list2 = authority.get(pmid2);
		HashMap<String,Integer> author_hash1 = new HashMap<String,Integer>();
		for(String author: author_list1)
			author_hash1.put(author, author_hash1.size());
		for(String author: author_list2){
			if(author_hash1.containsKey(author))
				score++;
		}
		score *= 4;
		return score;
	}
	
	public int Score_from_AuthorList(List<Name> list1, List<Name> list2){
		int score = 0;
		if(list1 == null || list2 == null || list1.size()==0 || list2.size() ==0)
			return score;
		for(int i=0;i<list1.size();i++)
		{
			int max = 0;
			int k = 0;
			for(int j = 0;j<list2.size();j++)
			{
				int tempscore = ComputeSingleNamePair(list1.get(i),list2.get(j));
				if(tempscore>max)
				{
					max = tempscore;
					k = j;
				}
			}
			if(max>0)
			{
				list2.remove(k);
				score += max;
			}
		}
		return score;
	}
	
	public int ComputeSingleNamePair(Name a, Name b)
	{
		int score = 0;
		if(a.first_name != null && b.first_name != null)
		{
			boolean firstname =  a.first_name.equals(b.first_name);
			boolean firstinitial = a.first_initial.equals(b.first_initial) && a.first_initial != null && b.first_initial != null;
			
			if(a.last_name!= null && b.last_name != null && a.last_name.equals(b.last_name) && (firstname || firstinitial) )
			{
				if(a.middle_initial != null && b.middle_initial != null)
				{
					if(a.middle_initial.equals(b.middle_initial)|| a.middle_initial.contains(b.middle_initial)|| b.middle_initial.contains(a.middle_initial))
					{
						score = 4;
						return score;
					}
					else
						return score;
				}
				else if(a.middle_initial == null && b.middle_initial == null)
				{
					score = 4;
					return score;
				}
				else
				{
					score = 1;
					return score;
				}
			}
			else
				return score;
		}
		else
		{
			if(a.last_name!= null && b.last_name != null && a.last_name.equals(b.last_name)&& a.first_initial != null && b.first_initial != null && a.first_initial.equals(b.first_initial))
			{
				if(a.middle_initial != null && b.middle_initial != null)
				{
					if(a.middle_initial.equals(b.middle_initial)|| a.middle_initial.contains(b.middle_initial)|| b.middle_initial.contains(a.middle_initial))
					{
						score = 4;
						return score;
					}
					else
						return score;
				}
				else if(a.middle_initial == null && b.middle_initial == null)
				{
					score = 4;
					return score;
				}
				else
				{
					score = 1;
					return score;
				}
			}
			else
				return score;
		}
	}
}
